import React, { Component } from 'react';
import * as Tabs from '@radix-ui/react-tabs';
import * as Select from '@radix-ui/react-select';
import { connect } from 'react-redux';
import { withConsumer } from '../../context';
import TextareaAutosize from 'react-textarea-autosize';
import styles from './index.module.scss';
import Image from 'next/image';
import {
  Sparkles,
  ChevronDown,
  ArrowRight,
  Square,
  Paperclip,
  Server,
  Star,
  Plus,
} from 'lucide-react';

import ep from '@/utils/eventproxy';
import router from 'next/router';
import { applied_list,generatorsChat,teamsChat } from '@/api/ai';
import { toast } from '@/components/basicComp/Toast';
import { parse } from 'partial-json';
import { update } from '@/utils/immutableUtil';
import ModelSelect from './ModelSelect';
import OptionsComp from './OptionsComp';
import AvaliableSelect from './AvaliableSelect';
import QuickCommands from './QuickCommands';
import McpSelect from './McpSelect';
import ConfirmDialog from '@/components/basicComp/Confirm';
import { intersection } from 'lodash';
import classNames from 'classnames';
import BlurReveal from '@/components/BlurReveal/index';
import ScrollListener from './ScrollListener';
import { chatMsgWs,setStr } from './wsHandle';
import SetText from './SetText';
import AIViewer from './AIViewer';


@withConsumer
@connect(({ ppt }) => ({
  selectedChat: ppt.selectedChat,
  selectedChatInit: ppt.selectedChatInit,
  chatLoading: ppt.chatLoading,
  selectedModel: ppt.selectedModel,
  messagesLength:ppt.messages.length,
}))
class Comp extends Component {
  textareaRef = React.createRef();
  state = {
    activeTab: 'artifacts',
    inputValue: '',
    codeTemplateMap: {},
    selectedTemplate: 'auto',
    mcpList: [],
    selectMcp: 'none',
    toolsMsg: '',
    showMcpSelect: false,
    mentionQuery: '',
    showConfirmDialog: false,

    confirmTitle: '',

    // 选择过的 mcp
    mcpSelectList: [],

    disabled:false,
  };

  componentDidMount = () => {
    const {
      value: { setController,initWs },
    } = this.props;
    initWs()
    setStr('')
    setController('ChatInput', this);
    ep.on('chatMsgWs', this.chatMsgWs);
    this.getMcp();
    this.textareaRef?.current?.focus();
    
  };

  componentWillUnmount = () => {
    const { value: { closeWs } } = this.props;
    closeWs()
    ep.removeListener('chatMsgWs', this.chatMsgWs);
    this.stopChat()
  }


  getMcp = async () => {
    var rs = await applied_list();
    if (rs.data?.code == 200) {
      var data = rs.data.data;
      this.setState({ mcpList: data });
    }
  };

  handleTabChange = (value) => {
    const { inputFocus } = this.props.value;
    this.setState({ activeTab: value });
    setTimeout(() => {
      inputFocus();
    }, 100);
  };

  stopChat = () => {
    setStr('')
    const {
      value: { changeState },
    } = this.props;
    this.isStopChat = true;
    // 当前进行的回复 （ws不处理了）
    this.dialog_segment_id = null
    if (this.heartbeatTimer) {
      clearTimeout(this.heartbeatTimer);
    }
    changeState({ chatLoading: false });
    console.log('Regenerating...');
  };

  handleSuggestionClick = (item) => {
    const { chatLoading } = this.props;
    if (chatLoading) return;
    this.setState({ inputValue: item.value, activeTab: 'artifacts' }, () => {
      this.handleSubmit();
    });
  };

  handleInputChange = (e) => {
    const inputValue = e.target.value;

    // Check for @ mentions
    // this.checkForMentions(inputValue);

    this.setState({ inputValue });
  };

  checkForMentions = (text) => {
    if (text.length < this.state.inputValue.length) {
      return;
    }

    if (text.length > 0 && text[text.length - 1] === '@') {
      this.setState({
        showMcpSelect: true,
        mentionQuery: '',
      });
      return;
    }
  };

  handleMcpSelectOpenChange = (open) => {
    this.setState(
      {
        showMcpSelect: open,
      },
      () => {
        // If dropdown is closed, focus on the textarea
        if (!open && this.textareaRef.current) {
          setTimeout(() => {
            this.textareaRef.current.focus();
          }, 0);
        }
      },
    );
  };

  selectMention = (serverName, serverItem) => {
    const { inputValue } = this.state;
    const lastAtIndex = inputValue.lastIndexOf('@');

    if (lastAtIndex !== -1) {
      // Replace the @query with the selected server
      const textBeforeAt = inputValue.substring(0, lastAtIndex);
      const textAfterQuery = inputValue.substring(
        lastAtIndex + this.state.mentionQuery.length + 1,
      );
      const newInputValue = `${textBeforeAt}@mcp:${serverName} ${textAfterQuery}`;

      var mcpSelectList = [...this.state.mcpSelectList, serverName];
      mcpSelectList = [...new Set(mcpSelectList)];
      this.setState({
        inputValue: newInputValue,
        showMcpSelect: false,
        mentionQuery: '',
        selectMcp: serverName,
        mcpSelectList: mcpSelectList,
      });

      // Focus the textarea and place cursor after the inserted mention
      setTimeout(() => {
        const textarea = this.textareaRef.current;
        if (textarea) {
          textarea.focus();
          const cursorPosition = textBeforeAt.length + serverName.length + 6; // +2 for @ and space
          textarea.setSelectionRange(cursorPosition, cursorPosition);
        }
      }, 0);
    }
  };

  handleSubmit = () => {
    const { inputValue, activeTab, codeTemplateMap, selectedTemplate } =
      this.state;
    const {
      chatLoading,
      selectedChat,
      selectedModel,
      value: { controller, changeState, scrollToBottom2 },
    } = this.props;
    var store = window.getStore();
    if (!inputValue.trim()) return;
    if (chatLoading) return;

    var { ppt } = store.getState();

    // 判断用户配置
    if (!selectedModel) {
      toast.error('Please configure your LLM settings');
      return;
    }

    changeState({
      chatLoading: true,
    });

    var queryText = this.getChatText(inputValue);

    // 添加用户消息
    var messages = [...ppt.messages];
    messages.push({
      role: 'user',
      content: [
        {
          type: 'text',
          text: queryText,
        },
      ],
      object: null,
    });

    // 机器人空数据
    messages.push({
      role: 'assistant',
      content: [],
      object: null,
      initData: true,
    });

    changeState({
      messages: messages,
      chatLoading: true,
    });

    setTimeout(() => {
      scrollToBottom2();
    }, 20);

    var reqData = {

    };

    // 处理代码逻辑
    if (activeTab == 'artifacts') {
      reqData = {
        ...reqData,
        code: true,
        artifacts_template_id: 0,
      };
      if (selectedTemplate != 'auto') {
        reqData.artifacts_template_id = codeTemplateMap[selectedTemplate].id;
      }
    }

    setTimeout(() => {
      this.sendMsg();
    }, 100);
  };

  closeMenu = () => {
    const {
      value: { setSidebar },
    } = this.props;
    var store = window.getStore();
    var { global } = store.getState();
    if (global.sidebarOpen) {
      setSidebar(false);
    }
  };

  sendMsg = async (params = {}, type) => {
    if (this.heartbeatTimer) {
      clearTimeout(this.heartbeatTimer);
    }

    const { inputValue, activeTab } = this.state;
    const {
      selectedModel,
      value: { changeState, controller, getSandbox, scrollToBottom2 },
    } = this.props;

    var reqData = {};
    var mcp_name_list = [];

    if (activeTab == 'mcp') {
      mcp_name_list = this.getMcpByStr(inputValue);
      mcp_name_list = intersection(mcp_name_list, this.state.mcpSelectList);
    }
    var query = this.getChatText(inputValue);

    if (type != 'user_confirm') {
      this.setState({ inputValue: '' });
    }

    var wsId = window.ws.config.uuid
    reqData = {
      client_id: wsId,
      conversation_id: this.props.selectedChat,
      generator_id: selectedModel,
      system: '你是个专业AI智能助手，善于人性化回答用户的问题，如有工具尽量考虑全面，可以一次调用多个工具',
      query: query,
      mcp_name_list: mcp_name_list,
      tools_group_name_list:[],
      "agent_instance_id": "",
      ...params,
    };


    this.lastReqData = {
      ...reqData,
      inputValue: inputValue,
    };

    try {
      var rs = await teamsChat(reqData)
      if (rs.data?.code == 200) {
        const { conversation_id,dialog_segment_id } = rs.data.data
        var id = conversation_id;
        this.conversation_id = id;
        window.localStorage.setItem('selectedPlanChat', id);
        this.dialog_segment_id = dialog_segment_id
        changeState({ selectedChat: id });
        // this.chatTimeNext()
      }else{
        this.chatClose()
      }
     
    } catch (error) {
      this.chatClose()
    }
  };

  setMessage = (item, index, isScroll = true) => {
    clearTimeout(this.scrollTime)
    const {
      value: { changeState, scrollToBottom2 },
    } = this.props;
    var store = window.getStore();
    var { ppt } = store.getState();
    var isAtBottom = this.isAtBottom

    var messages = [...ppt.messages];

    var i = messages.length - 1;
    if (index !== undefined) i = index;

    messages[i] = { ...messages[i], ...item };
    changeState({ messages: messages });

    if (isScroll) {
      if(true){
        this.scrollTime = setTimeout(() => {
          clearTimeout(this.scrollTime)
          scrollToBottom2();
        }, 20);
      }
     
    }
  };

  renderPersonaDropdown() {
    const { codeTemplateMap, selectedTemplate } = this.state;
    return (
      <Select.Root
        value={selectedTemplate}
        onValueChange={(value) => this.setState({ selectedTemplate: value })}
      >
        <Select.Trigger
          className={styles.personaTrigger}
          aria-label="Select persona"
        >
          <div className={styles.personaButton}>
            <Select.Value placeholder="Persona" />
            <Select.Icon>
              <ChevronDown size={16} />
            </Select.Icon>
          </div>
        </Select.Trigger>

        <Select.Portal>
          <Select.Content
            className={styles.selectContent}
            position="popper"
            side="top"
            sideOffset={5}
            align="start"
          >
            <Select.Viewport>
              <Select.Item
                value="auto"
                key={'auto'}
                className={styles.selectItem}
              >
                <Select.ItemText>
                  <div className={styles.itemText}>
                    <Sparkles
                      className="flex text-[#a1a1aa]"
                      width={14}
                      height={14}
                      style={{ marginRight: '10px' }}
                    />
                    {'Auto'}
                  </div>
                </Select.ItemText>
              </Select.Item>
              {Object.entries(codeTemplateMap).map(([templateId, template]) => (
                <Select.Item
                  key={templateId}
                  value={templateId}
                  className={styles.selectItem}
                >
                  <Select.ItemText>
                    <div className={styles.itemText}>
                      <img
                        className="flex"
                        src={`${router.basePath}/img/templates/${templateId}.svg`}
                        alt={templateId}
                        width={14}
                        height={14}
                        style={{ marginRight: '10px' }}
                      />
                      {template.name}
                    </div>
                  </Select.ItemText>
                </Select.Item>
              ))}
            </Select.Viewport>
          </Select.Content>
        </Select.Portal>
      </Select.Root>
    );
  }

  renderActionButtons() {
    const { chatLoading } = this.props;
    const { inputValue, activeTab,disabled } = this.state;
    const isDisabled = disabled;

    return (
      <div className={styles.actionButtons}>
        <OptionsComp activeTab={activeTab} />

        {!chatLoading ? (
          <button
            className={classNames(styles.submitButton, {
              [styles.noInputValue]: !inputValue.trim()
            })}
            disabled={isDisabled}
            onClick={this.handleSubmit}
          >
            <i
              className={'iconfont icon-fasong ' + styles.buttonIcon}
              style={{ fontSize: '18px' }}
            ></i>
          </button>
        ) : (
          <button
            className={styles.submitButton}
            disabled={isDisabled}
            onClick={() => { this.stopChat() }}
          >
            <Square fill="currentColor" size={16} className={styles.buttonIcon} />
          </button>
        )}
      </div>
    );
  }

  renderSuggestions() {
    return (
      <div className={styles.suggestionsContainer}>
        <div style={{ marginRight: '16px' }}>
          <AvaliableSelect mcpList={this.state.mcpList} />
        </div>

        <QuickCommands
          onValueChange={(item) => {
            this.handleSuggestionClick(item);
          }}
        />
      </div>
    );
  }

  onConfirmMcp = async () => {
    const {
      value: { changeState },
    } = this.props;
    this.setState({
      showConfirmDialog: false,
    });
    changeState({ chatLoading: true });
    var obj = {
      conversation_id: this.conversation_id,
      user_confirm: {
        id: this.user_confirm.id,
        user_confirmation_result: true,
      },
      ...this.lastReqData,
    };
    await this.sendMsg(obj, 'user_confirm');
    this.user_confirm = null;
  };

  onCancel = () => {
    const {
      value: { changeState },
    } = this.props;
    var store = window.getStore();
    var { ppt } = store.getState();

    const { messages } = ppt;
    this.user_confirm = null;
    this.setState({
      showConfirmDialog: false,
      inputValue: this.lastReqData.inputValue,
      toolsMsg: '',
      mcpSelectList: this.lastReqData.mcp_name_list,
    });
    this.textareaRef.current.focus();

    //之前添加2个消息清空掉
    var msgList = [...messages];
    msgList.splice(-2);
    changeState({ messages: msgList });
  };

  //返回 mcp 数组
  getMcpByStr = (str) => {
    const mcpParams =
      str
        .match(/@mcp:[^\s]+/g) // 匹配完整的 @mcp:参数
        ?.flatMap((param) => param.split(':')[1]) || []; // 提取参数部分
    return mcpParams;
  };

  //剔除所有 @mcp:xxx 部分，返回剩余文字
  getChatText = (str) => {
    if (!str) return '';
    // 去除所有 @mcp:xxx
    return str
      .replace(/@mcp:[^\s]+/g, '')
      .replace(/\s+/g, ' ')
      .trim();
  };

  chatTimeNext = ()=>{
    // clearTimeout(this.heartbeatTimer)
    // this.heartbeatTimer = setTimeout(()=>{
    //   clearTimeout(this.heartbeatTimer)
    //   console.log('超时终止')
    //   this.chatClose()
    //   this.getChatDetail()
    // },20000)
  }
  
  

  chatEnd = async ()=>{
    const {
      selectedChat,
      value: { changeState, controller, getSandbox, scrollToBottom2 },
    } = this.props;

    var store = window.getStore();
    var { ppt } = store.getState();
    const { messages } = ppt

    var reqData = this.lastReqData

    // 新会话 id
    if (!reqData.conversation_id) {
      changeState({ selectedChat: selectedChat });

      // 侧边栏
      var sidebar = controller.Left
      if (!sidebar) return
      sidebar.getList((data) => {
        var selectedItem = _.find(data, { id: selectedChat })
        if (selectedItem) {
          changeState({ selectedChat: selectedItem.id, selectedItem: selectedItem });
          if (typeof window !== 'undefined') {
            window.localStorage.setItem('selectedPlanChat', selectedItem.id);
          }
        }
      })
    }
    
    // 处理code逻辑
    if (reqData.code == true) {
      var fragment = JSON.parse(str);
      var rs = await getSandbox(fragment);
      const result = await rs.json();

      changeState({
        openPreview: true,
        codeResult: result,
        itemIndex: messages.length - 1,
        currentTab: 'fragment',
      });

      setTimeout(() => {
        this.closeMenu();
      }, 100);

      var ChatInput = controller.ChatInput;
      if (ChatInput) {
        ChatInput.setMessage({ result });
      }
    }

    this.chatClose()
  }

  chatClose = ()=>{
    const {value: { changeState,scrollToBottom2 }} = this.props;
    changeState({
      chatLoading: false,
      mcpSelectList: [],
    });

    setStr('')

    // setTimeout(() => {
    //   scrollToBottom2()
    // }, 50)

    // 处理toolsMsg
    setTimeout(() => {
      if (!this.user_confirm) {
        this.setState({ toolsMsg: '' });
      }
    }, 4000);
  }

  getChatDetail = ()=>{
    const { selectedChat,value: { controller }} = this.props;
    // 刷新列表
    var sidebar = controller.Left
    if(sidebar){
      sidebar.getChatDetail(selectedChat)
      console.log('刷新列表了啊啊')
    }
  }

  // ws 处理
  chatMsgWs = (data)=>{
    chatMsgWs(data,this)
  }

  shouldComponentUpdate = (np, ns) => update.call(this, np, ns);
  render() {
    const { value: { changeState  }} = this.props;
    const {
      activeTab,
      inputValue,
      mcpList,
      showMcpSelect,
      mentionQuery,
      toolsMsg,
      disabled,
    } = this.state;
    const { selectedChat, selectedChatInit, messagesLength } = this.props;

    var isCenter = false;
    if (!selectedChat && selectedChatInit && messagesLength == 0) {
      isCenter = true;
    }

    if (!selectedChatInit) return <></>;

    var placeholder = 'Describe your app...';
    return (
      <div className={styles.container}>
        
        {!selectedChat && messagesLength == 0 && (
          <div className={styles.hintTitle}>
            <BlurReveal duration={1900}>
              <div style={{ fontWeight: 450, marginBottom: 8 }} className={styles.hint}>👋Hello!</div>
            </BlurReveal>
            <BlurReveal duration={2300}>
              <div style={{ fontSize: 40, marginBottom: 40 }} className={styles.hint}>Ready to create a slideshow?</div>
            </BlurReveal>
          </div>
        )}

        <SetText />

        {
          true && <AIViewer />
        }

        {toolsMsg && (
          <div className={styles.toolsMsg}>
            <i className="iconfont icon-tongzhi"></i>
            {toolsMsg}
          </div>
        )}
        <BlurReveal duration={isCenter?1500:0} width = {'100%'}>
          <div className={styles.inputWrapper}>
            {showMcpSelect && (
              <div className={styles.mentionPopup}>
                <McpSelect
                  mcpList={mcpList}
                  open={showMcpSelect}
                  onSelect={this.selectMention}
                  onOpenChange={this.handleMcpSelectOpenChange}
                />
              </div>
            )}

            <div style={{ width: '100%', flex: '1' }}>
              <TextareaAutosize
                id="chat-textarea"
                ref={this.textareaRef}
                autoFocus={true}
                className={styles.input}
                placeholder={placeholder}
                value={inputValue}
                onChange={this.handleInputChange}
                minRows={1}
                maxRows={5}
                disabled={disabled}
                onKeyDown={(e) => {
                  if (e.key === '@' && activeTab == 'mcp') {
                    this.setState({ showMcpSelect: true });
                    return;
                  }

                  if (e.key === 'Enter' && !e.shiftKey) {
                    e.preventDefault();
                    this.handleSubmit();
                  } else if (e.key === 'Escape' && this.state.showMcpSelect) {
                    e.preventDefault();
                    this.setState({ showMcpSelect: false }, () => {
                      // Focus on the textarea after closing dropdown
                      if (this.textareaRef.current) {
                        setTimeout(() => {
                          this.textareaRef.current.focus();
                        }, 0);
                      }
                    });
                  }
                }}
               
              />
               {
                (()=>{
                  // 这种情况下 chat不展示 
                  if (!selectedChat && selectedChatInit && messagesLength === 0) {
                    return;
                  }
                  // 添加监听器（不渲染任何可见元素）
                  return (
                    <ScrollListener 
                      elementId="chat-container" 
                      threshold={30} 
                      onScrollBottom={(isAtBottom)=>{
                        if(this.isAtBottom === isAtBottom) return
                        // console.log(isAtBottom)
                        this.isAtBottom = isAtBottom
                      }}
                    />
                  )
                })()
               }
                
            </div>

            <div className={styles.options}>
              <div className={styles.optionsLeft}>
                <div className={styles.chatInput}>
                  <Tabs.Root
                    value={activeTab}
                    // onValueChange={this.handleTabChange}
                  >
                    <Tabs.List
                      className={styles.tabs}
                      aria-label="Choose interface type"
                    >
                      <Tabs.Trigger className={styles.tab} value="mcp">
                        Chat
                      </Tabs.Trigger>
                      <Tabs.Trigger className={styles.tab} value="artifacts">
                        Build
                      </Tabs.Trigger>
                    </Tabs.List>
                  </Tabs.Root>
                </div>
              </div>
              <div className={styles.optionsRight}>
                {/* {activeTab == 'artifacts' &&
                Object.keys(this.state.codeTemplateMap).length > 0 && (
                  <>{this.renderPersonaDropdown()}</>
                )} */}
                <ModelSelect />
                {this.renderActionButtons()}
              </div>
            </div>
          </div>

          {isCenter && (
            <div className={styles.callWord} style={{ height: '80px' }}>
              {this.renderSuggestions()}
            </div>
          )}
        </BlurReveal>
        <ConfirmDialog
          isOpen={this.state.showConfirmDialog}
          title={`Confirm Mcp`}
          message={this?.user_confirm?.message}
          onCancel={() => {
            this.onCancel();
          }}
          onConfirm={async () => {
            this.onConfirmMcp();
          }}
          cancelText="Cancel"
          confirmText="Submit"
        />
      </div>
    );
  }
}

export default Comp;
